package wangjg.dbfx.mapping;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;

import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;


/**
 * 
 * @author wangjg
 * 
 * This class is thread-safe.
 */
public class EntityInfoManager{
	private static final HashMap<Class<?>,EntityInfo> metaMap = new HashMap<Class<?>,EntityInfo>();
	
	private String table_prefix = null;
	
	public void setTable_prefix(String table_prefix) {
		this.table_prefix = table_prefix;
	}

	public EntityInfo getEntityInfo(Class<?> c){
		EntityInfo ei=(EntityInfo) metaMap.get(c);
		if(ei==null){
			synchronized(metaMap){
				if((ei=metaMap.get(c))==null){
					ei = _getEntityInfo(c);
					metaMap.put(c, ei);
				}
			}
		}
		return ei;
	}
	
	private EntityInfo _getEntityInfo(Class<?> c){
	    EntityInfo ei = new EntityInfo();
	    ei.setTable(c.getSimpleName());
		Table t = c.getAnnotation(Table.class);
		if(t!=null&&t.name()!=null&&t.name().length()!=0){
			ei.setTable(t.name());
		}
		if(this.table_prefix!=null){
			ei.setTable(this.table_prefix+ei.getTable());
		}
	    BeanInfo beanInfo;
		try {
			beanInfo = Introspector.getBeanInfo(c);
		} catch (IntrospectionException e) {
			e.printStackTrace();
			return null;
		}
	    PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
	    for(PropertyDescriptor p:pds){
	    	Method writeMethod=p.getWriteMethod();
	    	if(writeMethod==null){
	    		continue;
	    	}
	    	Method readMethod=p.getReadMethod();
	    	if(readMethod.getAnnotation(Transient.class)!=null){
	    		continue;
	    	}
	    	
			String col_name = p.getName();
			Column col = readMethod.getAnnotation(Column.class);
			if (col!=null && col.name() != null && col.name().length() != 0) {
				col_name = col.name();
			}
			col_name = col_name.toUpperCase();//大写
			FieldInfo fi=new FieldInfo();
			fi.setFieldName(p.getName());
			fi.setColumnName(col_name);
			fi.setReadMethod(readMethod);
			fi.setWriteMethod(writeMethod);
			fi.setFiledType(p.getPropertyType());
			
			GeneratedValue gv=readMethod.getAnnotation(GeneratedValue.class);
			if(gv!=null){
				GenerationType gt=gv.strategy();
				if(gt!=null && (gt==GenerationType.IDENTITY || gt==GenerationType.SEQUENCE || gt==GenerationType.AUTO)){
					fi.setAuto(true);
				}
			}
			if(readMethod.getAnnotation(Id.class)!=null){
				ei.setId(fi);
			}
			
			ei.putFieldInfo(fi);
	    }
	    return ei;
	}
	
	private static String toCamelMode(String name){
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<name.length();i++){
			char c = name.charAt(i);
			if(c=='_' && i<name.length()-1){
				c = name.charAt(++i);
				c = Character.toUpperCase(c);
			}
			sb.append(c);
		}
		return sb.toString();
	}
	
	private static String toPlankMode(String name){
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<name.length();i++){
			char c = name.charAt(i);
			if(Character.isUpperCase(c)){
				sb.append('_');
				c = Character.toLowerCase(c);
			}
			sb.append(c);
		}
		return sb.toString();
	}

}
